import time
import requests
import rsa
import binascii
import re
import random
import json
from PIL import Image #安装pillow
from urllib.parse import quote_plus
import  base64

'''如果没有开启登录保护，则不要输入验证码就可以登录
   如果开启登录保护，则输入验证码就可以登录
'''
#构造Requests Header
agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36SSSS'
headers ={
    'User-Agent':agent,
    'Connection':'keep-alive'
}
#访问初始页面带上cookies
session  = requests.session()

login_url = "http://weibo.com/login.php"
try:
    session.get(login_url,headers=headers,timeout=2)
except:
    session.get(login_url,headers= headers)

#对用户名进行预处理
def get_su(userName):
     userName_quote = quote_plus(userName)
     userName_base64 = base64.standard_b64encode(userName_quote.encode("utf-8"))
     return  userName_base64.decode("utf-8")

# 获取预登录之前的参数  servicetime  none pubkey  rsakv
def get_serverdata(su):
    pre_url = "http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su="
    pre_url = pre_url + su + "&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.18)&_="
    pre_url = pre_url + str(int(time.time() * 1000))
    pre_data_res = session.get(pre_url, headers=headers)
    sever_data = eval(pre_data_res.content.decode("utf-8").replace("sinaSSOController.preloginCallBack", ''))
    return sever_data


#对密码进行预处理
def get_password(password, servertime, nonce, pubkey):
    rsaPublickey = int(pubkey, 16)
    key = rsa.PublicKey(rsaPublickey, 65537)  # 创建公钥
    message = str(servertime) + '\t' + str(nonce) + '\n' + str(password)  # 拼接明文js加密文件中得到
    message = message.encode("utf-8")
    passwd = rsa.encrypt(message, key)  # 加密
    passwd = binascii.b2a_hex(passwd)  # 将加密信息转换为16进制。
    return passwd


#获取验证码图片
def get_cha(pcid):
    cha_url = "http://login.sina.com.cn/cgi/pin.php?r="
    cha_url = cha_url + str(int(random.random() * 100000000)) + "&s=0&p="
    cha_url = cha_url + pcid
    cha_page = session.get(cha_url, headers=headers)
    with open("cha.png", 'wb') as f:
        f.write(cha_page.content)
        f.close()
    try:
        im = Image.open("cha.png")
        im.show()
        im.close()
    except:
        print(u"请到当前目录下，找到验证码后输入")

#登录 返回用户ID
def login(username,password):
    # su 是加密后的用户名
    su = get_su(username)
    sever_data = get_serverdata(su)
    servertime = sever_data["servertime"]
    nonce = sever_data['nonce']
    rsakv = sever_data["rsakv"]
    pubkey = sever_data["pubkey"]
    showpin = sever_data["showpin"]
    password_secret = get_password(password, servertime, nonce, pubkey)

    postdata = {
        'entry': 'weibo',
        'gateway': '1',
        'from': '',
        'savestate': '7',
        'useticket': '1',
        'pagerefer': "http://login.sina.com.cn/sso/logout.php?entry=miniblog&r=http%3A%2F%2Fweibo.com%2Flogout.php%3Fbackurl",
        'vsnf': '1',
        'su': su,
        'service': 'miniblog',
        'servertime': servertime,
        'nonce': nonce,
        'pwencode': 'rsa2',
        'rsakv': rsakv,
        'sp': password_secret,
        'sr': '1366*768',
        'encoding': 'UTF-8',
        'prelt': '115',
        'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
        'returntype': 'META'
    }
    login_url = 'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)'
    if showpin == 0:
        login_page = session.post(login_url, data=postdata, headers=headers)
    else:
        pcid = sever_data["pcid"]
        get_cha(pcid)
        postdata['door'] = input(u"请输入验证码")
        login_page = session.post(login_url, data=postdata, headers=headers)
    login_loop = (login_page.content.decode("GBK"))
    # print(login_loop)
    pa = r'location\.replace\([\'"](.*?)[\'"]\)'
    try:
        loop_url = re.findall(pa, login_loop)[0]
        # print(loop_url)
        # 此处还可以加上一个是否登录成功的判断，下次改进的时候写上
        login_index = session.get(loop_url, headers=headers)
        uuid = login_index.text
        uuid_pa = r'"uniqueid":"(.*?)"'
        uuid_res = re.findall(uuid_pa, uuid, re.S)[0]
        web_weibo_url = "http://weibo.com/%s/profile?topnav=1&wvr=6&is_all=1" % uuid_res
        weibo_page = session.get(web_weibo_url, headers=headers)
        weibo_pa = r'<title>(.*?)</title>'
        # print(weibo_page.content.decode("utf-8"))
        userID = re.findall(weibo_pa, weibo_page.content.decode("utf-8", 'ignore'), re.S)[0]
        print(u"欢迎你 %s, " % userID)
        return uuid_res
    except:
        print("用户名或者密码错误!")



##
'''
发送微博 目前只支持纯文本微博发送
text 微博内容
userId  用户ID
'''
def sendWeiBo(text,userId):
    sendUrl ="http://weibo.com/aj/mblog/add?ajwvr=6&__rnd="+str(int(time.time() * 1000))
    postData ={
        'location': 'v6_content_home',
        'text': text,
        'appkey': "",
        'style_type': 1,
        'pic_id':'',
        'pdetail': '',
        'rank':'0',
        'rankid' :'',
        'module': 'stissue',
        'pub_source' : 'main_',
        'pub_type': 'dialog',
        '_t': 0,
    }
    headers1 = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 QQBrowser/3.9.3943.400',
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded',
        "Connection": 'keep-alive',
         'Referer': 'http://weibo.com/u/%s/home?topnav=1&wvr=6' % userId,
    }
    sendReponse = session.post(sendUrl, data=postData, headers=headers1)
    data = json.loads(str(sendReponse.text))
    code = str(data['code'])
    print(code)
    if ('100000' == code):
        print(userId + "\t发送微博成功")
    else:
        print(userId + "\t发送微博失败")
        msg = str(data['msg'])
        print('发送微博失败原因：\t' + msg)

'''
转发微博分三步：
1、不知道什么鬼返回数据为：{'domain': 1, 'logo': 1, 'position': 1, 'nickname': 1}, 'code': '100000', 'msg': ''}
2、获取当前要转发微博的转发数及最后一次评论人信息
3、转发微博
注：前两bu可以省略 直接请求转发url
userId 当前登录用户id
mid
rid
text 转发理由
'''
def repostWeiBo(userId,mid,rid,text):
    header = {
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; rv:50.0) Gecko/20100101 Firefox/50.0",
        'Accept-Encoding': "gzip, deflate",
        'Content-Type': "application/x-www-form-urlencoded",
        'X-Requested-With': "XMLHttpRequest",
        'Referer': "http://weibo.com/u/%s/home?topnav=1&wvr=6" % userId,
        'Connection': "keep-alive",
    }
    url = 'http://weibo.com/aj/account/watermark?ajwvr=6&_t=0&__rnd=' +str(int(time.time() * 1000))
    pre_data_res = session.get(url, headers= header)
    data = json.loads(str(pre_data_res.text))
    header = {
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; rv:50.0) Gecko/20100101 Firefox/50.0",
        'Accept-Encoding': "gzip, deflate",
        'Content-Type': "application/x-www-form-urlencoded",
        'X-Requested-With': "XMLHttpRequest",
        'Referer': "http://weibo.com/u/%s/home?topnav=1&wvr=6" % userId,
        'Connection': "keep-alive",
    }
    url2 = 'http://weibo.com/aj/v6/mblog/repost/small?ajwvr=6&d_expanded=on&expanded_status=1&__rnd=%s&mid=%s' %(str(int(time.time() * 1000)),mid)
    pre_data_res = session.get(url2, headers=header)
    data = json.loads(str(pre_data_res.text))
    header = {
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; rv:50.0) Gecko/20100101 Firefox/50.0",
        'Accept-Encoding': "gzip, deflate",
        'Content-Type': "application/x-www-form-urlencoded",
        'X-Requested-With': "XMLHttpRequest",
        'Referer': "http://weibo.com/u/%s/home?topnav=1&wvr=6" % userId,
        'Connection': "keep-alive",
    }
    postData ={
        'pic_src': "",
        'pic_id': "",
        'appkey': "",
        'mid': mid,
        'style_type': "1",
        'mark': "",
        'reason': text,
        'location': "v6_content_home",
        'pdetail': "",
        'module': "",
        'page_module_id': "",
        'refer_sort': "",
        'rank': "0",
        'rankid': "",
        'group_source': "group_all",
        'rid': rid,
        '_t': "0",
    }
    url = 'http://weibo.com/aj/v6/mblog/forward?ajwvr=6&domain=%s&__rnd=%s'% (userId, str(int(time.time() * 1000)) )
    pre_data_res = session.post(url,data=postData, headers=header)
    data = json.loads(str(pre_data_res.text))
    code = str(data['code'])
    print(code)
    if ('100000' == code):
        print(userId + "\t转发微博成功")
    else:
        print(userId + "\t转发微博失败")
        msg = str(data['msg'])
        print('转发微博失败原因：' + msg)

'''
关注用户
oid 当前登录用户的id
uid 为需关注的用户id
'''
def attentionFans(oid,uid):
    sendUrl ="http://weibo.com/aj/f/followed?ajwvr=6&__rnd="+str(int(time.time() * 1000))
    postData= {
        'uid': uid,
        'objectid': '',
        'f': '1',
        'extra': '',
        'refer_sort': 'followed',
        'refer_flag': '1005050005_',
        'location': 'myfans_v6',
        'oid': oid,
        'wforce': '1',
        'nogroup': 'true',
        'template': '1',
        '_t': 0,
    }
    headers1 = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 QQBrowser/3.9.3943.400',
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded',
        "Connection": 'keep-alive',
         'Referer': 'http://weibo.com/%s/fans?from=100505&wvr=6&mod=headfans&current=fans' % oid,
    }
    sendReponse = session.post(sendUrl,data=postData,headers=headers1)
    data = json.loads(str(sendReponse.text))
    code = str(data['code'])
    print(code)
    if ('100000' == code):
        print(userId + "\t关注成功")
    else:
        print(userId + "\t关注失败")
        msg = str(data['msg'])
        print('关注失败原因：' + msg)


'''
取消关注用户
oid 当前登录用户的id
uid 为需取消关注的用户id
'''
def unAttentionFans(oid,uid):
    #请求URL
    sendUrl ="http://weibo.com/aj/f/unfollow?ajwvr=6&__rnd="+str(int(time.time() * 1000))
    postData ={
        'refer_sort': 'relationManage',
        'location': 'page_100505_myfollow',
        'refer_flag': 'unfollow',
        'uid': uid,
        'gid': 0
    }
    headers1 = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 QQBrowser/3.9.3943.400',
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded',
        "Connection": 'keep-alive',
         'Referer': 'http://weibo.com/%s/follow?rightmod=1&wvr=6'  % oid,
    }
    sendReponse = session.post(sendUrl,data=postData,headers=headers1)
    if(sendReponse.status_code!=200):
        print("程序异常")
    else:
        data = json.loads(str(sendReponse.text))
        code = str(data['code'])
        print(code)
        if ('100000' == code):
            print(userId + "\t取消关注成功")
        else:
            print(userId + "\t取消关注失败")
            msg = str(data['msg'])
            print('取消关注失败原因：' + msg)


'''
点赞
userId 当前登录用户id
rid
mid
返回code 100000表示成功
'''
def likeWeiBo(userId,rid,mid):
    #点赞的请求url
    sendUrl ="http://weibo.com/aj/v6/like/add?ajwvr=6"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 QQBrowser/3.9.3943.400',
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded',
        "Connection": 'keep-alive',
        'Referer': 'http://weibo.com/u/%s/home?topnav=1&wvr=6' % userId,
    }
    #准备数据
    postData ={
        'location': 'v6_content_home',
        'group_source': 'group_all',
        'rid': rid,
        'version': 'mini',
        'qid': 'heart',
        'mid': mid,
        'like_src': '1',
    }
    sendReponse = session.post(sendUrl, data=postData, headers=headers)
    data = json.loads(str(sendReponse.text))
    code = str(data['code'])
    print(code)
    if('100000'==code):
        print(userId +"\t点赞成功")
    else:
        print(userId +"\t点赞失败")
        msg = str(data['msg'])
        print('点赞失败原因：' +msg)

'''
评论指定微博
text  评论内容
uid  当前登录人的用户id
mid 微博id
rid 可选参数
'''
def weiBoComment(text, uid, mid, rid):
    header = {
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; rv:50.0) Gecko/20100101 Firefox/50.0",
        'Accept-Encoding': "gzip, deflate",
        'Content-Type': "application/x-www-form-urlencoded",
        'X-Requested-With': "XMLHttpRequest",
        'Referer': "http://weibo.com/u/%s/home?topnav=1&wvr=6" % uid,
        'Connection': "keep-alive",
    }
    url = 'http://weibo.com/aj/v6/comment/add?ajwvr=6&__rnd=%s' % str(time.time() * 1000)
    postData = {
        'act': "post",
        'mid': mid,
        'uid': uid,
        'forward': "0",
        'isroot': "0",
        'content': text,  # 评论内容
        'location': "v6_content_home",
        'module': "scommlist",
        'group_source': "group_all",
        'rid': rid,
        'pdetail': "",
        '_t': "0",
    }
    pre_data_res = session.post(url, data=postData, headers=header)
    data = json.loads(str(pre_data_res.text))
    print("POST" + str(data))
if __name__ == "__main__":
    username = input(u'用户名：')
    password = input(u'密码：')
    userId = login(username, password)
    print(userId)
    if(None == userId):
        print(username +"login failed!")
    else:
        # mid  对应feed_time:4054723852285280
        # weiBoComment("大爱",userId,"4054723852285280","")
        # likeWeiBo(userId, '','4054723852285280')
        # sendWeiBo("缺个口罩!",userId)
        # attentionFans(userId, "1909377960")
        # unAttentionFans(userId, "1909377960")
        repostWeiBo(userId, "4054723852285280", "", "不错1!")




